// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#ifndef YHAIDA_WEAKCALLBACK_H
#define YHAIDA_WEAKCALLBACK_H
#include "../logging/Logging.h"
#include <functional>
#include <memory>

namespace yhaida
{
  // A barely usable WeakCallback

  /*
   *先检测该CLASS的生命期，再考虑是否要执行后面的函数
   */
  template <typename CLASS, typename... ARGS>
  class WeakCallback
  {
  public:
    // function -> void (CLASS::*)(ARGS...)
    // std::bind(&CLASS::xxx,this,ARGS...)
    // std::function<void(CLASS *, ARGS...)>
    WeakCallback(const std::weak_ptr<CLASS> &object,
                 const std::function<void(CLASS *, ARGS...)> &function)
        : _object(object), _function(function)
    {
    }

    // Default dtor, copy ctor and assignment are okay

    void operator()(ARGS &&...args) const
    {
      std::shared_ptr<CLASS> ptr(_object.lock());
      if (ptr)
      {
        _function(ptr.get(), std::forward<ARGS>(args)...);
      }
      else
      {
        LOG_TRACE << "expired";
      }
    }

  private:
    std::weak_ptr<CLASS> _object;
    std::function<void(CLASS *, ARGS...)> _function;
  };
  /*
  template <typename T, typename... ARG>
  void show(T value, ARG... arg)
  {
    cout << value << endl;
    show(arg...);
  }
  */
  template <typename CLASS, typename... ARGS>//第二个形参是任意长的成员函数指针
  WeakCallback<CLASS, ARGS...> makeWeakCallback(const std::shared_ptr<CLASS> &object,
                                                void (CLASS::*function)(ARGS...))
  {
    // function -> void (CLASS::*)(ARGS...)
    return WeakCallback<CLASS, ARGS...>(object, function);
  }

  template <typename CLASS, typename... ARGS>
  WeakCallback<CLASS, ARGS...> makeWeakCallback(const std::shared_ptr<CLASS> &object,
                                                void (CLASS::*function)(ARGS...) const)
  {
    return WeakCallback<CLASS, ARGS...>(object, function);
  }

} // namespace muduo

#endif // MUDUO_BASE_WEAKCALLBACK_H
